<?php

/*
 * CopyRight  : (C)2012-2099 HaoTeam Inc.
 * Document   : Auth.php
 * Created on : 2022-6-19 14:53:36
 * Author     : Tiger <1192851302@qq.com>
 * Description: This is NOT a freeware, use is subject to license terms.
 *              这即使是一个免费软件,使用时也请遵守许可证条款,得到当时人书面许可.
 *              未经书面许可,不得翻版,翻版必究;版权归属 HaoTeam Inc;
 */

namespace app\api\controller;

use app\Request;
use haoteam\service\UtilService;
use haoteam\service\SmsService;
use haoteam\service\SessionService;
use think\facade\Cache;
use think\facade\Log;
use app\models\User;
use app\models\UserToken;

/**
 * @title Auth
 * Class Auth
 * Tiger <1192851302@qq.com> 2022-6-19 14:53:36
 */
class Auth {

    /**
     * @title 短信验证码
     * @author Tiger <1192851302@qq.com>
     * @url /api/sms/code
     * @method POST
     * @param name:phone type:string require:1 default:1 other: desc:手机号码
     * @return array:数组值#
     */
    public function sms_code(Request $request) {
        list($phone, $type) = UtilService::postMore([['phone', 0], ['type', '']], $request, true);
        if (!preg_match("/^1[3-9]\d{9}$/", $phone)) {
            return app('json')->fail('手机号不正确');
        }
        $time = 120;
        if (Cache::get('code_' . $phone)) {
            return app('json')->fail($time . '秒内有效');
        }
        $code = rand(100000, 999999);
        $res = SmsService::send($phone, SmsService::VERIFICATION_CODE, compact('code', 'time'));
        if ($res['status'] == 400) {
            return app('json')->fail('短信平台验证码发送失败' . $res['msg'] ?? '');
        }
        Cache::set('code_' . $phone, $code, $time);
        return app('json')->successful($res['msg'] ?? '发送失败', compact('time'));
    }

    /**
     * 手机注册
     * @author Tiger <1192851302@qq.com>
     * @param Request $request
     * @return type
     */
    public function register(Request $request) {
        $post = UtilService::postMore([
                    'mobile',
                    'invite',
                    'password',
                    'repassword',
                    'openid',
                    'user_group',
                    'vercode',
                    'platform',
                    'spread_spid'
        ]);
        $post['uid'] = date('ymdhis');
        $validate = new \app\api\validates\UserValidate();
        if ($validate->scene('register')->check($post) == false) {
            return app('json')->fail($validate->getError());
        }
        $verifyCode = Cache::get('code_' . $post['mobile']);
        if (empty($verifyCode)) {
            return app('json')->fail('请先获取验证码');
        }
        if (substr($verifyCode, 0, 6) != $post['vercode']) {
            return app('json')->fail('验证码错误');
        }

        try {
            User::register(null, $post['mobile'], $post['openid'] ?? '', $post['password'], $post['platform'] ?? null, $post['spread_spid'] ?? '', $post['user_group'] ?? 0);
        } catch (\Exception $exc) {
            return app('json')->fail($exc->getMessage());
        }

        //注册后立即登录
        $userModel = new User();
        $user = $userModel->with(['group', 'verify'])->where('mobile', $post['mobile'])->withoutField(['password', 'salt'])->find();
        try {
            $token = UserToken::createToken($user, 'api');
            //写入登录
            SessionService::instance()->set(compact('user'), $token['token']);
        } catch (\Exception $exc) {
            return app('json')->fail($exc->getMessage());
        }
        return app('json')->successful('注册成功！', ['userInfo' => $user, 'token' => $token['token'], 'expires_time' => strtotime($token['expires_time'])]);
    }

    /**
     * 密码登录
     * @author Tiger <1192851302@qq.com>
     * @param Request $request
     * @return type
     */
    public function login(Request $request) {
        [$mobile, $password] = UtilService::postMore([
                    'mobile',
                    'password',
                        ], $request, true);
        if (empty($password)) {
            return app('json')->fail('密码不能为空');
        }
        if (empty($mobile)) {
            return app('json')->fail('手机号不能为空');
        }
        $userModel = new User();
        $user = $userModel->with(['group', 'verify'])->where('mobile', $mobile)->find();
        if (empty($user)) {
            return app('json')->fail('账号不存在');
        }
        if ($user->password !== encrypt_password($password, $user->salt)) {
            return app('json')->fail('账号或密码错误');
        }
        $user->last_time = date('Y-m-d H:i:s');
        $user->save();
        $user->salt = null;
        try {
            $token = UserToken::createToken($user, 'api');
            //写入登录
            SessionService::instance()->set(compact('user'), $token['token']);
        } catch (\Exception $exc) {
            return app('json')->fail($exc->getMessage());
        }
        return app('json')->successful('登陆成功！', ['userInfo' => $user, 'token' => $token['token'], 'expires_time' => strtotime($token['expires_time'])]);
    }

    /**
     * @title 第三方登录
     * @description 接口说明
     * @author Tiger <1192851302@qq.com>
     * @url /api/third/login
     * @method POST
     * @param name:code type:string require:1 default: other: desc:code
     * @return array:数组值#
     */
    public function third_login(Request $request) {
        [$code, $spread_spid, $third_type, $platform] = UtilService::postMore([
                    ['code', 0],
                    ['spread_spid', 0],
                    ['third_type', 'TikTok'],
                    ['platform', '']
                        ], $request, true);

        if (empty($code)) {
            return app('json')->fail('授权失败');
        }
        try {
            switch ($third_type) {
                case 'TikTok':
                    $userInfoCong = \haoteam\service\TikTokService::instance()->session($code);
                    break;
                case 'custom':
                    $userInfoCong = \haoteam\service\CustomService::instance()->session($code);
                    $extra = $userInfoCong;
                    break;
                default:
                    $userInfoCong = \haoteam\service\EasyWeChatService::miniapp()->auth->session($code);
                    break;
            }
            $nickname = $userInfoCong['nickname'] ?? null;
            $mobile = $userInfoCong['mobile'] ?? null;
            $openid = $userInfoCong['openid'];
            $unionId = $userInfoCong['unionid'] ?? null;
            $session_key = $userInfoCong['session_key'] ?? null;
        } catch (\Exception $e) {
            Log::error('获取session_key失败 | ' . $e->getTraceAsString());
            return app('json')->fail('获取session_key失败' . $e->getMessage());
        }
        if (empty($openid)) {
            return app('json')->fail('openid获取失败');
        }
        $userModel = new User();
        $user = $userModel->with(['group', 'verify'])->where('openid', $openid)->withoutField(['password', 'salt'])->find();
        if (empty($user)) {
            $user = User::register($nickname, $mobile, $openid, null, $platform, $spread_spid, 0, $extra ?? []);
        } else {
            $user->last_time = date('Y-m-d H:i:s');
            $user->save();
        }

        try {
            $token = UserToken::createToken($user, 'api');
            //写入登录
            SessionService::instance()->set(compact('user'), $token['token']);
        } catch (\Exception $exc) {
            Log::error('写入登录失败', ['line' => $exc->getLine(), 'message' => $exc->getMessage()]);
            return app('json')->fail($exc->getMessage());
        }
        return app('json')->successful('登陆成功！', ['userInfo' => $user, 'token' => $token['token'], 'expires_time' => strtotime($token['expires_time'])]);
    }

    /**
     * 验证登录
     * @author Tiger <1192851302@qq.com>
     * @param Request $request
     * @return type
     */
    public function verify_login(Request $request) {
        [$mobile, $vercode, $openid, $platform, $spread_spid] = UtilService::postMore([
                    'mobile',
                    'vercode',
                    ['openid', ''],
                    ['platform', ''],
                    ['spread_spid', 0]
                        ], $request, true);
        if (empty($mobile)) {
            return app('json')->fail('手机号不能为空');
        }

        $verifyCode = Cache::get('code_' . $mobile);
        if (empty($verifyCode)) {
            return app('json')->fail('请先获取验证码');
        }
        if (substr($verifyCode, 0, 6) != $vercode) {
            return app('json')->fail('验证码错误');
        }

        $userModel = new User();
        $user = $userModel->with(['group', 'verify'])->where('mobile', $mobile)->withoutField(['password', 'salt'])->find();
        if (empty($user)) {
            //return app('json')->fail('账号不存在');
            $user = User::register(null, $mobile, $openid, null, $platform, $spread_spid);
        }
        $user->openid = $openid;
        $user->last_time = date('Y-m-d H:i:s');
        $user->save();
        try {
            $token = UserToken::createToken($user, 'api');
            //写入登录
            SessionService::instance()->set(compact('user'), $token['token']);
        } catch (\Exception $exc) {
            return app('json')->fail($exc->getMessage());
        }
        return app('json')->successful('登陆成功！', ['userInfo' => $user, 'token' => $token['token'], 'expires_time' => strtotime($token['expires_time'])]);
    }

    /**
     * 重置密码
     * @author Tiger <1192851302@qq.com>
     * @param Request $request
     * @return type
     */
    public function forgot_password(Request $request) {
        $post = UtilService::postMore([
                    'mobile',
                    'password',
                    'repassword',
                    'vercode'
        ]);
        $verifyCode = Cache::get('code_' . $post['mobile']);
        if (empty($verifyCode)) {
            return app('json')->fail('请先获取验证码');
        }
        if (substr($verifyCode, 0, 6) != $post['vercode']) {
            return app('json')->fail('验证码错误');
        }

        $validate = new \app\api\validates\UserValidate();
        if ($validate->scene('forgot')->check($post) == false) {
            return app('json')->fail($validate->getError());
        }

        $userModel = new User();
        $user = $userModel->where('mobile', $post['mobile'])->find();
        if (empty($user)) {
            return app('json')->fail('账号不存在');
        }

        $post['salt'] = create_salt();
        $post['password'] = encrypt_password($post['password'], $post['salt']);

        try {
            User::update($post, ['id' => $user->id]);
        } catch (\Exception $exc) {
            return app('json')->fail($exc->getMessage());
        }

        return app('json')->successful('重置成功');
    }
}
